package com.dbflow5.runtime;

import com.dbflow5.adapter.ModelAdapter;
import com.dbflow5.query.SQLOperator;
import com.dbflow5.structure.ChangeAction;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.app.Context;

import static com.dbflow5.SqlUtils.getNotificationUri;

/**
 * The default use case, it notifies via the [ContentResolver] system.
 *
 * Specify the content URI authority you wish to use here. This will get propagated
 * everywhere that changes get called from in a specific database.
 */
public class ContentResolverNotifier implements ModelNotifier {
    private final Context context;
    String authority;

    public ContentResolverNotifier(Context context, String authority){
        this.context = context;
        this.authority = authority;
    }

    @Override
    public <T> void notifyModelChanged(T model, ModelAdapter<T> adapter, ChangeAction action) {
        if (FlowContentObserver.shouldNotify()) {
            DataAbilityHelper.creator(context).notifyChange(
                    getNotificationUri(authority, adapter.table(), action,
                            adapter.getPrimaryConditionClause(model).conditions()));
        }
    }

    @Override
    public <T> void notifyTableChanged(Class<T> table, ChangeAction action) {
        if (FlowContentObserver.shouldNotify()) {
            DataAbilityHelper.creator(context).notifyChange(getNotificationUri(authority, table, action, null, null));
        }
    }

    @Override
    public TableNotifierRegister newRegister() {
        return new FlowContentTableNotifierRegister(context, authority);
    }

    static class FlowContentTableNotifierRegister implements TableNotifierRegister {
        private final Context context;
        String contentAuthority;

        private final FlowContentObserver flowContentObserver = new FlowContentObserver(contentAuthority, null);
        private OnTableChangedListener tableChangedListener = null;

        FlowContentTableNotifierRegister(Context context, String contentAuthority){
            this.context = context;
            this.contentAuthority = contentAuthority;

            flowContentObserver.addOnTableChangedListener(internalContentChangeListener);
        }

        private final OnTableChangedListener internalContentChangeListener = (table, action) -> {
            if(tableChangedListener != null){
                tableChangedListener.onTableChanged(table, action);
            }
        };

        @Override
        public boolean isSubscribed() {
            return !flowContentObserver.isSubscribed();
        }

        @Override
        public <T> void register(Class<T> tClass) {
            flowContentObserver.registerForContentChanges(context, tClass);
        }

        @Override
        public <T> void unregister(Class<T> tClass) {
            flowContentObserver.unregisterForContentChanges(context);
        }

        @Override
        public void unregisterAll() {
            flowContentObserver.removeTableChangedListener(internalContentChangeListener);
            this.tableChangedListener = null;
        }

        @Override
        public void setListener(OnTableChangedListener listener) {
            this.tableChangedListener = listener;
        }
    }
}
